﻿using System;
using System.Collections;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Net;
using System.Xml;
using System.Xml.Xsl;
using System.IO;
using System.Collections.Specialized;
using System.Configuration;

namespace green
{
    /// <summary>
    /// Summary description for $codebehindclassname$
    /// </summary>
    [WebService(Namespace = "http://webutilis.net/service/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class LiteWeb : IHttpHandler
    {
        private string _session = Constants.nullSession;
        private int _docId = -1;
        //private litedb _db = new litedb();
        private litedb _db = new litedb(Global.getConnection());
        public void ProcessRequest(HttpContext context)
        {
            //if (_db == null)
            //{
            //    string apppt = Path.Combine(context.Request.PhysicalApplicationPath, "green.sqlite");
            //    _db = new litedb(String.Format("Data Source={0}", apppt));
            //}
            _session = context.Request.Params["lises"];
            _session = (_session == null) ? Constants.nullSession : _session;
            _docId = Convert.ToInt32(context.Request.Params["did"]);
            switch (context.Request.HttpMethod)
            {
                case "GET": HandleRequest(context); break;
                case "POST":HandlePost(context); break;
                case "PUT": context.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed; break;
                default: context.Response.StatusCode = (int)HttpStatusCode.BadRequest; break;
            }
        }

        #region POST Handlers
        private void HandlePost(HttpContext context)
        {
            string reqUri = context.Request.PathInfo;
            switch (reqUri)
            {
                case "/imgnew": _newImage(context); break;
                case "/imgupd": _updateImage(context); break;
                case "/tile": _getTile(context); break;
                default: context.Response.StatusCode = 400; break;
            }
        }

        //private void _updateImage(HttpContext context)
        //{
        //    try
        //    {
        //        string title = context.Request.Params["imgTitle"];
        //        int id = Convert.ToInt32(context.Request.Form["imgId"]);
        //        HttpPostedFile F = context.Request.Files[0];
        //        byte[] buff = new byte[F.ContentLength];
        //        F.InputStream.Read(buff, 0, F.ContentLength);
        //        if (_db.updateImage(id, title, F.ContentType, F.ContentLength, buff))
        //        {
        //            _reportResult(context, "Image Uploaded - " + title, F.ContentLength);
        //        }
        //        else
        //        {
        //            _reportResult(context, "Filed to Upload - " + title, F.ContentLength);
        //        }
        //    }
        //    catch (Exception e)
        //    {
        //        _reportError(context, e);
        //    }
        //}

        private void _updateImage(HttpContext context)
        {

            try
            {

                string title = context.Request.Params["imgTitle"];
                int id = Convert.ToInt32(context.Request.Form["imgId"]);
                string tileid = context.Request.Form["tileId"];
                HttpPostedFile F = context.Request.Files[0];
                byte[] buff = new byte[F.ContentLength];
                F.InputStream.Read(buff, 0, F.ContentLength);

                _db.updateImage(id, title, F.ContentType, F.ContentLength, buff);
                context.Response.Redirect(

                @"green.ashx/tile?did=" + tileid);
                context.Response.Flush();

            }

            catch (Exception e)
            {

                //_reportError(context, e);
            }

        }



        private void _newImage(HttpContext context)
        {
            try
            {
                string title = context.Request.Params["imgTitle"];
                HttpPostedFile F = context.Request.Files[0];
                title = (title == null) ? F.FileName : title;
                byte[] buff = new byte[F.ContentLength];
                F.InputStream.Read(buff, 0, F.ContentLength);
                if (_db.insertImage(title, F.ContentType, F.ContentLength, buff))
                {
                    _reportResult(context, "Image Uploaded - " + title, F.ContentLength);
                }
                else _reportResult(context, "Filed to Upload - " + title, F.ContentLength);
            }
            catch (Exception e)
            {
                _reportError(context, e);
            }
        }
        
        #endregion

        #region GET Handlers

        private void HandleRequest(HttpContext context)
        {
            string reqUri = context.Request.PathInfo;
            switch (reqUri)
            {
                //case "/newusr": _getNewAccount(context); break;
                case "/login": _getSession(context); break;
                case "/css": _getStyle(context); break;
                case "/pg": _getPage(context); break;
                case "/js": _getScript(context); break;
                case "/img": _getImage(context); break;
                case "/scr": _getTileJs(context); break;
                case "/tile": _getTile(context); break;
                default: context.Response.StatusCode = 400; break;
            }
        }

        private void _getSession(HttpContext context)
        {
            NameValueCollection nvC = context.Request.Params;
            string respStr = "";
            string login = nvC["login"];
            string hmac = nvC["hmac"];
            string session = nvC["lises"];
            string pwdHash = _db.getPwdHash(login);
            if (Constants.IsHmacValid(session, pwdHash, hmac) && _db.setUsrSession(login, session))
            {
                respStr = String.Format(Constants.jsonLogin, 0, "Ok!", session);

            }
            else
            {
                session = Constants.nullSession;
                respStr = String.Format(Constants.jsonLogin, 1, "Wrong credentials!", session);
            }

            HttpCookie coo = new HttpCookie("lises");
            coo.Value = session;
            context.Response.Cookies.Add(coo);
            context.Response.Write(respStr);
            context.Response.StatusCode = 200;
            context.Response.Flush();
        }


        private void _getStyle(HttpContext context)
        {
            try
            {
                string scr = _db.GetCss(_docId);
                context.Response.ContentType = "text/css";
                context.Response.StatusCode = 200;
                context.Response.Write(scr);
                context.Response.Flush();
            }
            catch (Exception e) { _reportError(context, e); }
        }

        private void _getPage(HttpContext context)
        {
            try
            {
                PageInfo pg = _db.GetPage(_docId);
                context.Response.ContentType = pg.Mime;
                context.Response.StatusCode = 200;
                context.Response.Write(pg.Body);
                context.Response.Flush();
            }
            catch (Exception e) { _reportError(context, e); }
        }

        private void _getScript(HttpContext context)
        {
            try
            {
                string scr = _db.GetScript(_docId);
                context.Response.ContentType = "text/javascript";
                context.Response.StatusCode = 200;
                context.Response.Write(scr);
                context.Response.Flush();
            }
            catch (Exception e) { _reportError(context, e); }
        }

        private void _getImage(HttpContext context)
        {
            try
            {
                ImageInfo img = _db.GetImage(_docId);
                context.Response.OutputStream.Write(img.Body, 0, img.Body.Length);
                context.Response.StatusCode = 200;
                context.Response.ContentType = img.Mime;
                context.Response.Flush();
            }
            catch (Exception e) { _reportError(context, e); }
        }

        private void _getTileJs(HttpContext context)
        {
            try
            {
                string tileJs = _db.getTileScript(_docId, _session);
                context.Response.ContentType = "application/javascript";
                context.Response.StatusCode = 200;
                context.Response.Write(tileJs);
                context.Response.Flush();
            }
            catch (Exception e) { _reportError(context, e); }
        }

        private void _getTile(HttpContext context)
        {
            TileInfo Ti = _db.getTileInfo(_docId, _session);
            switch (Ti.TileStatus)
            {
                case 1: _tileQuery(Ti, context); break;//select...
                case 2: _tileAction(Ti, context); break;//insert,delete,update ...
                case 3: _tileProcess(Ti, context); break;//insert,delete,update ... then select.
                default: context.Response.Write(""); //context.Response.StatusCode = 403;
                         context.Response.Flush(); 
                         break;
            }

        }

        private void _tileProcess(TileInfo Ti, HttpContext context)
        {
            try
            {
                string json = _db.ActionResponse(Ti, context.Request.Params);
                if (json.StartsWith("{error:0,"))
                {
                    _tileQuery(Ti, context);
                }
                else
                {
                    throw new Exception(json);
                }

            }
            catch (Exception e) { _reportError(context, e); }

        }

        private void _tileAction(TileInfo Ti, HttpContext context)
        {
            try
            {
                string json = _db.ActionResponse(Ti, context.Request.Params);
                context.Response.ContentType = Ti.TileMime;
                context.Response.StatusCode = 200;
                context.Response.Write(json);
                context.Response.Flush();
            }
            catch (Exception e) { _reportError(context, e); }
        }

        private void _tileQuery(TileInfo Ti, HttpContext context)
        {
            try
            { 
                XmlDocument _xDoc = _db.QueryXml(Ti, context.Request.Params);
                XslCompiledTransform T = new XslCompiledTransform();
                T.Load(Ti.TileXsl);
                T.Transform(_xDoc, null, context.Response.OutputStream);
                context.Response.ContentType = Ti.TileMime;
                context.Response.StatusCode = 200;
                context.Response.Flush();
            }
            catch (Exception e) { _reportError(context, e); }
        }
        
        #endregion
        private static void _reportResult(HttpContext context, string message, int arg)
        {

            context.Response.Write(String.Format(Constants.jsonResponse, 0, message.Replace('\n', ' ').Replace('\r', ' '), arg));
            context.Response.StatusCode = 200;
            context.Response.Flush();
        }


        private static void _reportError(HttpContext context, Exception e)
        {

            //string msg = e.Message.Replace('\n', ' ').Replace('\r', ' ');
            context.Response.Write(String.Format(Constants.jsonResponse, 1, (e.Message + "::Source - " + e.Source).Replace('\n', ' ').Replace('\r', ' '), 0));
            context.Response.StatusCode = 200;
            context.Response.Flush();
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}
